package pers.brozen.anka.support.verify;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import pers.brozen.anka.support.web.response.ErrorCodes;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Objects;

/**
 * 应用层业务校验工具类，校验不通过会抛出 VerifyException
 *
 * @author Brozen
 * @since 2021-10-21
 */
@Slf4j
public class Verifies {


    /**
     * 校验表达式结果是否为true，不为true时抛出{@link VerifyException}
     *
     * @param expression boolean表达式结果
     * @param message 抛出异常的提示信息
     */
    public static void verify(boolean expression, String message) {
        if (!expression) {
            throw new VerifyException(ErrorCodes.PARAM_ERROR, message);
        }
    }


    /**
     * 校验表达式结果是否为true，不为true时抛出{@link VerifyException}
     *
     * @param expression boolean表达式结果
     * @param status 抛出异常的状态码
     */
    public static void verify(boolean expression, ErrorCodes status) {
        if (!expression) {
            if (status != null) {
                log.info("verify failed Status={} message={}", status.code, status.message);
            }
            throw new VerifyException(status);
        }
    }


    /**
     * 校验表达式结果是否为true，不为true时抛出{@link VerifyException}
     *
     * @param expression boolean表达式结果
     * @param status 抛出异常的状态码
     * @param message 错误提示信息
     */
    public static void verify(boolean expression, ErrorCodes status, String message) {
        if (!expression) {
            if (status != null) {
                log.info("verify failed Status={} message={} appendixMessage={}",
                        status.code, status.message, message);
            }
            throw new VerifyException(status, message);
        }
    }


    /**
     * 校验引用不为null，否则抛出{@link VerifyException}
     * @param ref 引用
     * @param status 抛出异常的状态码
     */
    @Nonnull
    public static <T> T notNull(T ref, ErrorCodes status) {
        verify(ref != null, status);
        return ref;
    }


    /**
     * 校验引用不为null，否则抛出{@link VerifyException}
     * @param ref 引用
     * @param message 错误提示信息
     */
    @Nonnull
    public static <T> T notNull(@Nullable T ref, String message) {
        verify(ref != null, message);
        return ref;
    }


    /**
     * 校验引用不为null，否则抛出{@link VerifyException}
     * @param ref 引用
     * @param status 抛出异常的状态码
     * @param message 错误提示信息
     */
    @Nonnull
    public static <T> T notNull(@Nullable T ref, ErrorCodes status, String message) {
        verify(ref != null, status, message);
        return ref;
    }


    /**
     * 校验字符串不为空，否则抛出{@link VerifyException}
     * @param str 待校验字符串
     * @param status 抛出异常的状态码
     */
    public static String notBlank(@Nullable String str, ErrorCodes status) {
        verify(StringUtils.isNotBlank(str), status);
        return str;
    }


    /**
     * 校验字符串不为空，否则抛出{@link VerifyException}
     * @param str 待校验字符串
     * @param message 错误提示信息
     */
    public static String notBlank(@Nullable String str, String message) {
        verify(StringUtils.isNotBlank(str), message);
        return str;
    }


    /**
     * 校验字符串不为空，否则抛出{@link VerifyException}
     * @param str 待校验字符串
     * @param status 抛出异常的状态码
     * @param message 错误提示信息
     */
    public static String notBlank(@Nullable String str, ErrorCodes status, String message) {
        verify(StringUtils.isNotBlank(str), status, message);
        return str;
    }


    /**
     * 校验集合不为空，否则抛出{@link VerifyException}
     * @param collection 待校验集合
     * @param status 抛出异常的状态码
     */
    public static <E> Collection<E> notEmpty(@Nullable Collection<E> collection, ErrorCodes status) {
        verify(CollectionUtils.isNotEmpty(collection), status);
        return collection;
    }


    /**
     * 校验集合不为空，否则抛出{@link VerifyException}
     * @param collection 待校验集合
     * @param message 错误提示信息
     */
    public static <E> Collection<E> notEmpty(@Nullable Collection<E> collection, String message) {
        verify(CollectionUtils.isNotEmpty(collection), message);
        return collection;
    }


    /**
     * 校验集合不为空，否则抛出{@link VerifyException}
     * @param collection 待校验集合
     * @param status 抛出异常的状态码
     * @param message 错误提示信息
     */
    public static <E> Collection<E> notEmpty(@Nullable Collection<E> collection, ErrorCodes status, String message) {
        verify(CollectionUtils.isNotEmpty(collection), status, message);
        return collection;
    }


    /**
     * 校验两个对象相等，否则抛出{@link VerifyException}。
     * @param o1 待校验的对象 A
     * @param o2 待校验的对象 B
     * @param message 抛出异常时的错误提示信息
     */
    public static void equals(Object o1, Object o2, String message) {
        verify(Objects.equals(o1, o2), message);
    }


    /**
     * 校验两个对象相等，否则抛出{@link VerifyException}。
     * @param o1 待校验的对象 A
     * @param o2 待校验的对象 B
     * @param status 抛出异常时的错误码
     */
    public static void equals(Object o1, Object o2, ErrorCodes status) {
        verify(Objects.equals(o1, o2), status);
    }


    /**
     * 校验两个对象相等，否则抛出{@link VerifyException}。
     * @param o1 待校验的对象 A
     * @param o2 待校验的对象 B
     * @param status 抛出异常时的错误码
     * @param message 抛出异常时的错误提示信息
     */
    public static void equals(Object o1, Object o2, ErrorCodes status, String message) {
        verify(Objects.equals(o1, o2), status, message);
    }

}
